package com.xjscrm.console.common.util;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.xjscrm.common.constant.CacheKey;
import com.xjscrm.common.constant.ResponseMsg;
import com.xjscrm.common.exception.BusinessException;
import com.xjscrm.common.result.ResponseCode;
import com.xjscrm.common.utils.Base64EncryptUitl;
import com.xjscrm.common.utils.MapObjExchangeuUtils;
import com.xjscrm.common.utils.OkHttpUtils;
import com.xjscrm.console.entity.WxAccessTokenResult;
import com.xjscrm.console.vo.LoginVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class TokenUitls {

    private static Logger logger = LoggerFactory.getLogger(TokenUitls.class);

    @Value("${login.tokenInfoItems}")
    private   String tokenInfoItems;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${wx.appId}")
    private String appId;
    @Value("${wx.secret}")
    private String secret;
    @Value("${wx.getWxAccessTokenUrl}")
    private String getWxAccessTokenUrl;

    @Autowired
    private RestTemplate restTemplate;

    public  String  generateToken(Map userInfo){
        {
            StringBuffer token = new StringBuffer();
            logger.info("tokenInfoItems is {}",tokenInfoItems);
            String[] items = tokenInfoItems.split(",");
            for (String item : items) {
                Object obj = userInfo.get(item.trim());
                token.append(null == obj ? "" : obj).append("_");
            }
            Date date=new Date();
            SimpleDateFormat sdfTime = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            String loginTime = sdfTime.format(date);
            token.append(loginTime);
            return Base64EncryptUitl.encodeBy3DESAndBase64(token.toString());
        }
    }

    public  String  generateRefreshToken(){
        //设置refreshToken
         return UUID.randomUUID().toString();
    };


    public  void saveTokenInfo(String token, Map userInfo,String refreshToken) {
        try {
            //设置auth_token
            String tokenKey =String.format(CacheKey.AUTH_TOKEN,token);
            redisTemplate.opsForHash().putAll(tokenKey,userInfo);
            redisTemplate.expire(tokenKey,CacheKey.AUTH_TOKEN_EXPIRE, TimeUnit.SECONDS);
            //设置refresh_token
            String refreshTokenkey=String.format(CacheKey.REFRESH_TOKEN,refreshToken);
            redisTemplate.opsForHash().putAll(refreshTokenkey,userInfo);
            redisTemplate.expire(refreshTokenkey,CacheKey.REFRESH_TOKEN_EXPIRE, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.error("err:{}",e);
        }
    }

    public void loginOut(HttpServletRequest request){
        String authToken = request.getHeader("Auth-Token");
        String refreshToken= request.getHeader("Refresh—Token");
        redisTemplate.delete(String.format(CacheKey.AUTH_TOKEN,authToken));
        redisTemplate.delete(String.format(CacheKey.REFRESH_TOKEN,refreshToken));
    }

    public Object refreshToken(HttpServletRequest request) {
        String refresh= request.getHeader("Refresh-Token");
        Map entries = redisTemplate.opsForHash().entries(String.format(CacheKey.REFRESH_TOKEN, refresh));
        if (entries == null ||entries.isEmpty()) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.REFRESHTOKEN_EXPIRE);
        }
        LoginVO loginVO = BeanUtil.mapToBean(entries, LoginVO.class, true);
        if(loginVO==null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.REFRESHTOKEN_ERROR);
        }
        //删除老的refreshTOken
        redisTemplate.delete(String.format(CacheKey.REFRESH_TOKEN,refresh));
        //设置新的token
        Map<String,Object> map=new HashMap<>();
        Map userInfo = MapObjExchangeuUtils.objToMap(map, loginVO);
        //token,用户信息存入redis
        String accessToken = generateToken(userInfo);
        String refreshToken = generateRefreshToken();
        logger.info("accessToken is {},refreshToken is {}",accessToken,refreshToken);
        saveTokenInfo(accessToken,userInfo,refreshToken);
        loginVO.setAuthToken(accessToken);
        loginVO.setRefreshToken(refreshToken);
        return loginVO;
    }


    public WxAccessTokenResult getWxAccessToken(String code) {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("appid",appId);
        paramMap.put("secret",secret);
        paramMap.put("code",code);
        paramMap.put("grant_type","authorization_code");
        WxAccessTokenResult wxAccessTokenResult;
        try {
            String generateParam = generateParam(paramMap);
            String url=getWxAccessTokenUrl+generateParam;
            ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, null, String.class);
            String body = result.getBody();
            logger.info("body:"+body);
           if(body==null){
               throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION,ResponseMsg.NET_ERROR);
           }
            wxAccessTokenResult = JSONObject.parseObject(body, WxAccessTokenResult.class);
           if(wxAccessTokenResult==null){
               throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION,ResponseMsg.WXACCESS_TOKEN_FAIL);
           }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return wxAccessTokenResult;
    }


    public String generateParam(Map<String, String> paramMap) {
        StringBuilder urlBuilder = new StringBuilder();
        if (paramMap != null && paramMap.size() > 0) {
            for (String key : paramMap.keySet()) {
                urlBuilder
                        .append(key)
                        .append("=")
                        .append(paramMap.get(key))
                        .append("&");
            }
        }
        return urlBuilder.substring(0, urlBuilder.length() - 1);
    }
}
